package com.mes.cloud.utils;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.collections.MapUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 利用开源组件POI3.0.2动态导出EXCEL文档
 * ReportExcelUtil 替换
 * @param <T> 应用泛型，代表任意一个符合javabean风格的类
 *            注意这里为了简单起见，boolean型的属性xxx的get方式为getXxx(),而不是isXxx()
 *            byte[]表jpg格式的图片数据
 */
@Deprecated
public class ExcelUtils<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtils.class);

    // 最大行数
    public static final int MAX_LINE = 65535;
    // nothing
    public static final int KEEP_NOTHING = 0;

    public static final int KEEP_NUMBER = 1;

    public static final int KEEP_DATE = 2;

    /**
     * 导出excel文件
     * @param response
     * @param title
     * @param titleMap
     * @param dataset
     * @param keepFlag
     */
    public void exportExcelKeepCell(HttpServletResponse response, String title, Map<String, String> titleMap, Collection<T> dataset, int keepFlag) {
        // 超出最大导出行数直接返回
        if (dataset.size() > MAX_LINE) {
            //CsvUtils.exportFile(response, titleMap, dataset);
            return;
        }

        makeExcel(response, title, titleMap, dataset, null, null, keepFlag);
    }

    private void makeExcel(HttpServletResponse response, String title, Map<String, String> titleMap, Collection<T> dataset,
                           Map<String, Map> propertyCustomTextMap, String pattern, int keepFlag) {
        response.setContentType("octets/stream");
        response.addHeader("Content-Disposition", "attachment;filename=output.xls");

        OutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
        }

        this.exportExcelInside(title, titleMap, dataset, out, propertyCustomTextMap, pattern, keepFlag);
    }

    public void exportExcel(String title, Map<String, String> titleMap, Collection<T> dataset, OutputStream out, String pattern) {
        this.exportExcelInside(title, titleMap, dataset, out, null, pattern, KEEP_NOTHING);
    }

    public void exportExcel(String title, Map<String, String> titleMap, Collection<T> dataset, OutputStream out, Map<String, Map> propertyCustomTextMap, String pattern) {
        this.exportExcelInside(title, titleMap, dataset, out, propertyCustomTextMap, pattern, KEEP_NOTHING);
    }

    /*
    *增加一个@param 参数propertyCustomTextMap用于定制字段值对应显示内容的集合。
     */
    private void exportExcelInside(String title, Map<String, String> titleMap, Collection<T> dataset, OutputStream out, Map<String, Map> propertyCustomTextMap,
                                   String pattern, int keepFlag) {

        //    // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();


        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyy-MM-dd";
        }

        if (StringUtils.isEmpty(title)) {
            title = "数据页";
        }else {
            try {
                title = org.apache.commons.lang3.StringUtils.toEncodedString(title.getBytes("iso-8859-1"), Charset.forName("utf-8"));
                title = title.substring(0,title.lastIndexOf("."));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        //创建sheet页
        HSSFSheet sheet = createSheet(title, null, workbook);

        //创建标题的样式
        HSSFCellStyle tableTitleStyle = createCellStyleForTableTitle(workbook);

        //创建标题的字体
        HSSFFont tableTitleFont = createFontForTableTitle(workbook);

        // 把标题字体应用到表格的样式
        tableTitleStyle.setFont(tableTitleFont);

        //创建正文的样式
        HSSFCellStyle tableBodyStyle = createCellStyleForTableBody(workbook);

        // 创建正文的字体
        HSSFFont tableBodyFont = workbook.createFont();

        tableBodyFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);

        // 把正文字体应用到正文的样式
        tableBodyStyle.setFont(tableBodyFont);

        // 声明一个画图的顶级管理器
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();


        createData(tableTitleStyle, titleMap, propertyCustomTextMap, sheet, dataset, tableBodyStyle, pattern, patriarch, workbook, keepFlag);

        closeSource(workbook, out);
    }

    private void closeSource(HSSFWorkbook workbook, OutputStream out) {
        try {
            workbook.write(out);
        } catch (Throwable e) {
            LOGGER.error(e.getMessage(), e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                    out.flush();
                }

            } catch (Throwable e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 设置表格内容
     */
    private void createData(HSSFCellStyle tableTitleStyle, Map<String, String> titleMap, Map<String, Map> propertyCustomTextMap, HSSFSheet sheet, Collection<T> dataset, HSSFCellStyle tableBodyStyle, String pattern, HSSFPatriarch patriarch, HSSFWorkbook workbook, int keepFlag) {

        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        HSSFFont font3 = workbook.createFont();
        font3.setColor(HSSFColor.BLUE.index);

        // 样式提前生产好，因为样式数有限制
        HSSFCellStyle numberStyle = this.createCellStyleForNumber(workbook, font3);
        HSSFCellStyle dateStyle = this.createCellStyleForDate(workbook, font3);

        if (!StringUtils.isEmpty(titleMap) && titleMap.size() > 0) {

            int i = 0;

            for (Map.Entry<String, String> entry : titleMap.entrySet()) {

                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(tableTitleStyle);
                HSSFRichTextString text = new HSSFRichTextString(entry.getValue());
                cell.setCellValue(text);
                i++;

            }
        }

        // 遍历集合数据，产生数据行
        Iterator<T> it = dataset.iterator();

        int index = 0;

        while (it.hasNext()) {

            index++;

            row = sheet.createRow(index);

            T t = (T) it.next();


            // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
            PropertyDescriptor[] descriptors = BeanUtilsBean.getInstance().getPropertyUtils().getPropertyDescriptors(t);

            int j = 0;
            for (Map.Entry<String, String> entry : titleMap.entrySet()) {

                HSSFCell cell = row.createCell(j);
                cell.setCellStyle(tableBodyStyle);

                for (int i = 0; i < descriptors.length; i++) {

                    PropertyDescriptor descriptor = descriptors[i];
                    String fieldName = descriptor.getName();

                    if (!entry.getKey().equals(fieldName)) {
                        continue;
                    }

                    StringBuffer methodNameBuffer = new StringBuffer();
                    methodNameBuffer.append("get");
                    methodNameBuffer.append(fieldName.substring(0, 1).toUpperCase());
                    methodNameBuffer.append(fieldName.substring(1));
                    j++;

                    try {

                        Method getMethod = descriptor.getReadMethod();
                        Object value = getMethod.invoke(t, new Object[]{});
                        if (!MapUtils.isEmpty(propertyCustomTextMap)) {
                            value = propertyCustomTextMap.getOrDefault(fieldName, Collections.emptyMap()).getOrDefault(value, value);
                        }

                        // 判断值的类型后进行强制类型转换
                        String textValue = null;

                        if (value instanceof Boolean) {
                            boolean bValue = (Boolean) value;
                            textValue = "1";
                            if (!bValue) {
                                textValue = "0";
                            }
                        } else if (value instanceof Date) {
                            Date date = (Date) value;

                            // 需要保留日期类型时，进行此操作
                            if ((keepFlag & KEEP_DATE) == KEEP_DATE) {
                                cell.setCellStyle(dateStyle);
                                cell.setCellValue(date);
                                continue;
                            }

                            try {
                                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                                textValue = sdf.format(date);
                            } catch (Throwable e) {
                                LOGGER.error(e.getMessage(), e);
                            }

                        } else if (value instanceof byte[]) {

                            // 有图片时，设置行高为60px;
                            row.setHeightInPoints(60);

                            // 设置图片所在列宽度为80px,注意这里单位的一个换算
                            sheet.setColumnWidth(i, (int) (35.7 * 80));

                            byte[] bsValue = (byte[]) value;

                            HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,
                                    1023, 255, (short) 6, index, (short) 6, index);

                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);

                            patriarch.createPicture(anchor, workbook.addPicture(
                                    bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));

                        } else {
                            // 其它数据类型都当作字符串简单处理
                            if (StringUtils.isEmpty(value)) {
                                textValue = null;
                            } else {
                                textValue = value.toString();
                            }

                            // TODO: 暂时无法支持数据位数大于Double类型的情况
                            // 需要保留数字类型时，进行此操作
                            if ((keepFlag & KEEP_NUMBER) == KEEP_NUMBER && value instanceof Number) {
                                cell.setCellStyle(numberStyle);
                                cell.setCellValue(Double.parseDouble(textValue));
                                continue;
                            }
                        }

                        HSSFRichTextString richString = new HSSFRichTextString(textValue);
                        richString.applyFont(font3);

                        cell.setCellValue(richString);

                    } catch (Throwable e) {

                        LOGGER.error(e.getMessage(), e);

                    }
                }
            }
        }
    }

    /**
     * 生成一个sheet页
     *
     * @param title       sheet页的名字
     * @param columnWidth 表格列宽度,默认为15个字节
     * @return sheet页对象
     */
    private HSSFSheet createSheet(String title, Integer columnWidth, HSSFWorkbook workbook) {

        //sheet页
        HSSFSheet sheet = workbook.createSheet(title);

        // 设置表格默认列宽度为15个字节
        if (StringUtils.isEmpty(columnWidth)) {

            sheet.setDefaultColumnWidth(15);

        } else {

            sheet.setDefaultColumnWidth(columnWidth);

        }

        return sheet;
    }

    /**
     * 日期样式
     *
     * @return
     */
    private HSSFCellStyle createCellStyleForDate(HSSFWorkbook workbook, HSSFFont font) {
        // 生成一个样式
        HSSFCellStyle style = this.createCellStyleForTableBody(workbook);
        HSSFDataFormat format = workbook.createDataFormat();

        style.setFont(font);
        style.setDataFormat(format.getFormat("yyyy-mm-dd"));
        return style;
    }

    /**
     * 数字样式
     *
     * @return
     */
    private HSSFCellStyle createCellStyleForNumber(HSSFWorkbook workbook, HSSFFont font) {
        // 生成一个样式
        HSSFCellStyle style = this.createCellStyleForTableBody(workbook);

        style.setFont(font);
        style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.0000"));

        return style;
    }

    /**
     * 表格标题的样式
     *
     * @return
     */
    private HSSFCellStyle createCellStyleForTableTitle(HSSFWorkbook workbook) {
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置这些样式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

        return style;

    }

    /**
     * 表格标题的字体
     *
     * @return
     */
    private HSSFFont createFontForTableTitle(HSSFWorkbook workbook) {
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

        return font;
    }

    /**
     * 表格正文的样式
     *
     * @return
     */
    private HSSFCellStyle createCellStyleForTableBody(HSSFWorkbook workbook) {
        HSSFCellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        return style;

    }

}
